package frog

import (
	"encoding/gob"
	"encoding/json"
	"fmt"
	"os"
	"sort"

	"gitee.com/xntk2381/frog/egg"
)

// 定义常量
const (
	JSON_FILE_FORMAT = true // JSON格式较慢但易于调试
)

// EggTool 提供与蛋相关的工具方法
type EggTool struct{}

// LayEggs 利用序列化机制存盘
func LayEggs(env *Env) {
	sortFrogsOrderByEnergyDesc(env)

	// 打印青蛙能量信息
	if len(env.Frogs) > 0 {
		fmt.Printf("First frog energy=%v", env.Frogs[0].Energy)
		if len(env.Frogs) > 1 {
			fmt.Printf(",  Last frog energy=%v,  ", env.Frogs[len(env.Frogs)-1].Energy)
			for i, frog := range env.Frogs {
				if i > 0 {
					fmt.Print(", ")
				}
				fmt.Printf("%v", frog.Energy)
			}
		}
		fmt.Println()
	}

	try(func() {
		newEggs := make([]*egg.Egg, 0, env.EGG_QTY)
		for i := 0; i < env.EGG_QTY; i++ {
			// 使用接口方法获取青蛙并下蛋
			newEggs = append(newEggs, env.Frogs[i].LayEgg())
		}
		var filePath string
		if JSON_FILE_FORMAT {
			// JSON格式存储
			newEggsJSON, err := json.MarshalIndent(newEggs, "", "  ")
			if err != nil {
				fmt.Printf("JSON marshal error: %v\n", err)
				return
			}
			filePath = "eggs.json"
			err = os.WriteFile(filePath, newEggsJSON, 0644)
			if err != nil {
				fmt.Printf("Write file error: %v\n", err)
				return
			}
			fmt.Printf("Saved %d eggs to file '%s'\n", len(newEggs), filePath)
		} else {
			// 二进制格式存储
			filePath = "eggs.gob"
			file, err := os.Create(filePath)
			if err != nil {
				fmt.Printf("Create file error: %v\n", err)
				return
			}
			defer file.Close()

			encoder := gob.NewEncoder(file)
			err = encoder.Encode(newEggs)
			if err != nil {
				fmt.Printf("Encode error: %v\n", err)
				return
			}
			fmt.Printf("Saved %d eggs to file '%s'\n", len(newEggs), filePath)
		}

		env.Eggs = newEggs
		fmt.Printf("Saved  %d eggs to file %s\n", len(env.Eggs), filePath)
	}, func(err interface{}) {
		fmt.Printf("Error occurred: %s\n", err)
		// 希望把出现err的堆栈打印出来
		panic(err)

	})
}

// sortFrogsOrderByEnergyDesc 按能量降序排序青蛙
func sortFrogsOrderByEnergyDesc(env *Env) {
	sort.Slice(env.Frogs, func(i, j int) bool {
		return env.Frogs[i].Energy > env.Frogs[j].Energy
	})
}

// LoadEggs 从磁盘读入一批Egg
func LoadEggs(env *Env) {
	errorFound := false

	if JSON_FILE_FORMAT {
		filePath := "eggs.json"
		data, err := os.ReadFile(filePath)
		if err != nil {
			fmt.Printf("Read file error: %v\n", err)
			errorFound = true
		} else {
			// var newEggs []*egg.Egg
			err = json.Unmarshal(data, &env.Eggs)
			if err != nil {
				fmt.Printf("JSON unmarshal error: %v\n", err)
				errorFound = true
			} else {
				// env.SetEggs(newEggs)
				fmt.Printf("Loaded %d eggs from file '%s'.\n", len(env.Eggs), filePath)
			}
		}
	} else {
		filePath := "eggs.gob"
		file, err := os.Open(filePath)
		if err != nil {
			fmt.Printf("Open file error: %v\n", err)
			errorFound = true
		} else {
			defer file.Close()

			decoder := gob.NewDecoder(file)
			// var newEggs []*egg.Egg
			err = decoder.Decode(&env.Eggs)
			if err != nil {
				fmt.Printf("Decode error: %v\n", err)
				errorFound = true
			} else {
				fmt.Printf("2Loaded %d eggs from file '%s'.\n", len(env.Eggs), filePath)
			}
		}
	}

	if errorFound {
		fmt.Printf("No eggs files found, created %d new eggs to do test.\n", env.EGG_QTY)
		env.Eggs = make([]*egg.Egg, 0, env.EGG_QTY)
		for i := 0; i < env.EGG_QTY; i++ {
			env.Eggs = append(env.Eggs, egg.CreateBrandNewEgg())
		}
	}
}

// DeleteEggs 删除存在的蛋文件
func DeleteEggs() {
	var filePath string
	if JSON_FILE_FORMAT {
		filePath = "eggs.json"
	} else {
		filePath = "eggs.gob"
	}

	fmt.Printf("Delete exist egg file: '%s'\n", filePath)
	err := os.Remove(filePath)
	if err != nil {
		fmt.Printf("Delete file error: %v\n", err)
	}
}

// try-catch 模拟Java的try-catch
func try(block func(), catch func(interface{})) {
	defer func() {
		if r := recover(); r != nil {
			if catch != nil {
				catch(r)
			} else {
				fmt.Printf("Panic: %v\n", r)
			}
		}
	}()
	block()
}
